package hamaster.jpbc.gui;

import static hamaster.jpbc.gui.Messages.getString;
import static hamaster.jpbc.userconfig.ConfigKeys.LAST_LOG_SAVE_FOLDER;
import static java.awt.FlowLayout.LEFT;
import static java.awt.FlowLayout.RIGHT;
import static javax.swing.BoxLayout.Y_AXIS;
import static javax.swing.JFileChooser.APPROVE_OPTION;
import static javax.swing.JOptionPane.ERROR_MESSAGE;
import static javax.swing.JOptionPane.INFORMATION_MESSAGE;
import static javax.swing.JOptionPane.WARNING_MESSAGE;
import static javax.swing.JOptionPane.YES_NO_OPTION;
import static javax.swing.JOptionPane.YES_OPTION;
import static javax.swing.JOptionPane.showConfirmDialog;
import static javax.swing.JOptionPane.showMessageDialog;
import hamaster.jpbc.Main;
import hamaster.jpbc.gui.callback.AsynchronousCallback;
import hamaster.jpbc.mgr.SymmetricEncryptManager;

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Properties;
import java.util.Scanner;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JTextArea;
import javax.swing.filechooser.FileNameExtensionFilter;

public class VerifyPanel extends JPanel implements ActionListener, AsynchronousCallback {
	private static final long serialVersionUID = 1L;
	public static final int VERIFY_RESULT = 200;

	private File signed;
	private Properties metadata;
	private JButton verifyButton;
	private JButton saveButton;
	private JTextArea signInfo;
	private JProgressBar progressBar;
	private Main application;

	public VerifyPanel(Main application) {
		this.application = application;
		setLayout(new BoxLayout(this, Y_AXIS));
		add(new JLabel(Messages.getString("VerifyPanel.noDecryption"))); //$NON-NLS-1$
	}

	public void enable(File signed, Properties metadata) {
		removeAll();
		if ("true".equalsIgnoreCase(metadata.getProperty(SymmetricEncryptManager.SIGNED_MARK))) { //$NON-NLS-1$
			this.signed = signed;
			this.metadata = metadata;
			String format = Messages.getString("VerifyPanel.containSignature"); //$NON-NLS-1$
			signInfo = new JTextArea(String.format(format, signed.getName()));
			verifyButton = new JButton(Messages.getString("VerifyPanel.verifySignature")); //$NON-NLS-1$
			saveButton = new JButton(Messages.getString("VerifyPanel.saveResult")); //$NON-NLS-1$
			progressBar = new JProgressBar();
			progressBar.setValue(0);
			signInfo.setLineWrap(true);
			signInfo.setEditable(false);
			verifyButton.addActionListener(this);
			saveButton.setEnabled(false);
			saveButton.addActionListener(this);
			JPanel btnPanel = new JPanel(new FlowLayout(RIGHT));
			btnPanel.add(saveButton);
			btnPanel.add(verifyButton);
			JPanel progressPanel = new JPanel(new FlowLayout(LEFT));
			progressPanel.add(new JLabel(Messages.getString("VerifyPanel.verifyProgress"))); //$NON-NLS-1$
			progressPanel.add(progressBar);
			add(signInfo);
			add(progressPanel);
			add(btnPanel);
		} else {
			String format = Messages.getString("VerifyPanel.notContainSIgnature"); //$NON-NLS-1$
			add(new JLabel(String.format(format, signed.getName())));
		}
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		if (e.getSource() == this.verifyButton) {
			SignatureVerifyThread verify = new SignatureVerifyThread(signed, metadata, this);
			Thread t = new Thread(verify);
			t.start();
		} else if (e.getSource() == this.saveButton) {
			Thread save = new Thread() {
				@Override
				public void run() {
					JFileChooser saveChooser = new JFileChooser(signed.getParent());
					
					String recentLogFolder = Main.getUserConfig().getProperty(LAST_LOG_SAVE_FOLDER);
					if (recentLogFolder != null)
						saveChooser.setCurrentDirectory(new File(recentLogFolder));
					
					saveChooser.setFileFilter(new FileNameExtensionFilter(Messages.getString("VerifyPanel.txtExtenction"), "txt")); //$NON-NLS-1$ //$NON-NLS-2$
					int result = saveChooser.showDialog(VerifyPanel.this.application, Messages.getString("VerifyPanel.save")); //$NON-NLS-1$
					if (result == APPROVE_OPTION) {
						try {
							File txt = saveChooser.getSelectedFile();
							if (txt.exists()) {
								String format = Messages.getString("VerifyPanel.confirmOverwrite"); //$NON-NLS-1$
								int confirm = showConfirmDialog(VerifyPanel.this.application,
										String.format(format, txt.getName()),
										Messages.getString("VerifyPanel.doConfirm"), YES_NO_OPTION, WARNING_MESSAGE); //$NON-NLS-1$
								if (confirm != YES_OPTION)
									return;
							}
							String name = txt.getName();
							if (!name.toLowerCase().endsWith(".txt")) { //$NON-NLS-1$
								name += ".txt"; //$NON-NLS-1$
							}
							File logFile = new File(txt.getParentFile(), name);
							PrintWriter out = new PrintWriter(logFile);
							Scanner sn = new Scanner(signInfo.getText());
							out.println(Messages.getString("VerifyPanel.result")); //$NON-NLS-1$
							while (sn.hasNextLine()) {
								out.println(sn.nextLine());
							}
							sn.close();
							out.flush();
							out.close();
							showMessageDialog(VerifyPanel.this.application, Messages.getString("VerifyPanel.saveComplete"), getString("EncryptPanel.information"), INFORMATION_MESSAGE); //$NON-NLS-1$ //$NON-NLS-2$
							Main.getUserConfig().setProperty(LAST_LOG_SAVE_FOLDER, logFile.getParent());
						} catch (IOException e) {
							showMessageDialog(VerifyPanel.this.application, Messages.getString("VerifyPanel.saveError"), getString("EncryptPanel.error"), ERROR_MESSAGE); //$NON-NLS-1$ //$NON-NLS-2$
						}
					}
				}
			};
			save.start();
		}
	}

	@Override
	public void progressUpdated(int progress) {
		if (progress < 0)
			this.progressBar.setValue(0);
		else if (progress <= 100)
			this.progressBar.setValue(progress);
		else
			this.progressBar.setValue(100);
		if (progress == 100)
			this.saveButton.setEnabled(true);
	}

	@Override
	public void message(String content, int type) {
		switch (type) {
		case JOptionPane.ERROR_MESSAGE:
			showMessageDialog(application, content, getString("EncryptPanel.error"), type); //$NON-NLS-1$
			break;
		case JOptionPane.INFORMATION_MESSAGE:
			showMessageDialog(application, content, getString("EncryptPanel.information"), type); //$NON-NLS-1$
			break;
		case JOptionPane.WARNING_MESSAGE:
			showMessageDialog(application, content, getString("EncryptPanel.warning"), type); //$NON-NLS-1$
			break;
		case JOptionPane.QUESTION_MESSAGE:
			showMessageDialog(application, content, getString("EncryptPanel.question"), type); //$NON-NLS-1$
			break;
		case JOptionPane.PLAIN_MESSAGE:
			showMessageDialog(application, content, new String(), type);
			break;
		default:
			if (type == VERIFY_RESULT) {
				signInfo.setText(content);
			}
		}
	}
}
